﻿// 
//    Copyright 2010 The JaernCloud Project
// 
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
// 
//        http://www.apache.org/licenses/LICENSE-2.0
// 
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JaernCloud.Language.Compiler.Ast;

namespace JaernCloud.Language.Compiler {
    
    /// <summary>
    /// Additional C# code for the JaernCloud.atg generated Parser.cs
    /// </summary>
    public partial class Parser {

        public AstNode Root;

        bool IsNodeWithSelector() {
            scanner.ResetPeek();
            Token next = scanner.Peek();
            bool ret = la.kind == _colon || next.kind == _colon;
            return ret;
        }

        bool IsNodeWithBody() {
            scanner.ResetPeek();
            Token next = scanner.Peek();
            bool ret = la.kind == _nodeaction || la.kind == _begin || next.kind == _begin || next.kind == _foreach || next.kind == _if;
            return ret;
        }

        bool HasBody() {
            scanner.ResetPeek();
            if (la.kind == _begin) {
                return true;
            }
            if (la.kind == _EOF) {
                return false;
            }
            Token next = scanner.Peek();
            if (next.kind == _EOF) return false;
            int currentLine = la.line;
            while (next.line == currentLine)
            {
                if (next.kind == _begin)
                {
                    // found begin of body on same line
                    return true;
                }
                if (next.kind == _EOF)
                {
                    return false;
                }
                next = scanner.Peek();
            }
            // on a following line
            return next.kind == _begin;
        }

        bool HasForeachIn()
        {
            scanner.ResetPeek();
            Token next = scanner.Peek();
            return next.kind == _in;
        }

        bool HasQueryOperator(AstNode nodeDecl)
        {
            return nodeDecl.Query != null;
        }

        bool IsNodeInheritsFromSingle() {

            // if the next non-whitespace char is "}" or EOF
            // if the next non-empty line contains a node declaration operator eg. "->" ":" ";" "{" or a node constant

            scanner.ResetPeek();

            int currentLine = la.line;
            Token next = la;
            while (next.line == currentLine) {
                if (next.kind == _end || next.kind == _EOF) {
                    // this is the last node inside another node
                    return true;
                }
                if (next.kind == _begin || next.kind == _comma) {
                    // multiple inheritance or new node is beginning
                    return false;
                }
                next = scanner.Peek();
            }
            // we're on the next line(s) - see if a new node is being declared or if the current node is ended
            while (next.kind != _EOF) {
                switch (next.kind) {
                    case _end:
                    case _stringCon:
                    case _intCon:
                    case _realCon:
                    case _nodeaction:
                    case _colon:
                    case _comma:
                    case _semicolon:
                        return true;
                }
                next = scanner.Peek();
            }

            // not a match for single
            return false;

        }

    }
}
